package com.wh.wisdomsite.xbox.utils.json.impl;

import com.wh.wisdomsite.xbox.utils.json.JosnConverter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.concurrent.ConcurrentHashMap;

/**
 * XML转换(javax.xml接口实现)
 * @Package com.wh.wisdomsite.xbox.utils.json
 * @author 谢泽鹏
 * @date 2014年10月8日 下午4:02:14
 * @Copyright 个人版权所有
 * @Company 贵州万华科技有限公司Copyright (c) 2014
 * @version V1.0
 */
public class XmlConverter implements JosnConverter {

    private static final Log logger = LogFactory.getLog(XmlConverter.class);

    private static final ConcurrentHashMap<Class, JAXBContext> jaxbContexts = new ConcurrentHashMap<Class, JAXBContext>();


    /**
     * 将XML的string转换成Object
     * @param string xml字符串
     * @param clazz  转换对象
     * @param <T>    返回对象
     * @return
     */
    @Override
    public <T> T getObject(String string, Class<T> clazz) {
        try {
            StringReader reader = new StringReader(string);
            Unmarshaller unmarshaller = createUnmarshaller(clazz);
            return (T) unmarshaller.unmarshal(reader);
        } catch (JAXBException e) {
            e.printStackTrace();
            logger.error("getObject->>将字符串" + string + "转化为对象" + clazz.getName() + "时错误: " + e.getMessage());
            throw new RuntimeException(e);
        }
    }


    /**
     * 将Objcet转化成XML字符串
     * @param object 转换对象
     * @return
     */
    @Override
    public String getString(Object object) {
        StringWriter stringWriter = new StringWriter();
        Marshaller marshaller = createMarshaller(object.getClass());
        try {
            //格式化xml
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
            marshaller.marshal(object, stringWriter);
        } catch (JAXBException e) {
            e.printStackTrace();
            logger.error("getObject->>将对象" + object.getClass() + "流化为字符串错误: " + e.getMessage());
            throw new RuntimeException(e);
        }
            return stringWriter.getBuffer().toString();
    }


    /**
     * 根据clazz创建Unmarshaller
     * @param clazz objct对象
     * @return
     */
    private Unmarshaller createUnmarshaller(Class clazz) {
        try {
            JAXBContext jaxbContext = getJaxbContext(clazz);
            return jaxbContext.createUnmarshaller();
        } catch (JAXBException e) {
            e.printStackTrace();
            logger.error("getObject->>JAXB 创建Unmarshaller对象:" + clazz.getName() + "错误: " + e.getMessage());
            throw new RuntimeException(e);
        }
    }


    /**
     * 根据clazz创建Marshaller
     * @param clazz objct对象
     * @return
     */
    private Marshaller createMarshaller(Class clazz) {
        try {
            JAXBContext jaxbContext = getJaxbContext(clazz);
            return jaxbContext.createMarshaller();
        } catch (JAXBException e) {
            e.printStackTrace();
            logger.error("getObject->>JAXB 创建Marshaller对象:" + clazz.getName() + "错误: " + e.getMessage());
            throw new RuntimeException(e);
        }
    }


    /**
     * 根据clazz创建JAXBContext
     * @param clazz objct对象
     * @return
     */
    private JAXBContext getJaxbContext(Class clazz) {
        try {
            JAXBContext jaxbContext = jaxbContexts.get(clazz);
            if (jaxbContext == null) {
               jaxbContext = JAXBContext.newInstance(clazz);
               jaxbContexts.putIfAbsent(clazz, jaxbContext);
            }
            return jaxbContext;
        } catch (JAXBException e) {
             e.printStackTrace();
             logger.error("getObject->>JAXB 创建Instance对象: " + clazz.getName() + "错误: " + e.getMessage());
             throw new RuntimeException(e);
        }
    }


}
